﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using OSGeo.MapGuide;
using System.Xml;
using System.Text;
using System.Configuration;
using System.Collections.Specialized;
using System.Web.UI.HtmlControls;


namespace IGIS.Extensions.SearchInBlock
{
    //    public partial class _default : System.Web.UI.Page
    //    {
    //        protected void Page_Load(object sender, EventArgs e)
    //        {

    //        }
    //    }
    //}



    public partial class Cascade : utilityfunctions
    {
        private bool __debugMode = bool.Parse(ConfigurationManager.AppSettings["DEBUG_MODE"]);

        public const string KeySession = "SESSION";
        public const string KeyMapName = "MAPNAME";
        public const string KeyLayer1 = "LAYER1";
        public const string KeyLayer2 = "LAYER2";
        public const string KeyFilter = "FILTER";
        private const string KeyMatchLimit = "MR";
        private const string KeyProperty = "Property";
        private const string KeyFilterOperation = "FILTER_OPERATOP";
        private const string KeyACLayer = "ACLayer";
        public const string KeyACProperty = "ACProperty";
        private const string KeyIsString = "IsString";
        private const string KeyDistinct = "DISTINCT";
        private const string IdField1 = "IdField1";
        public const string SearchFld1 = "SearchFld1";
        private const string IdField2 = "IdField2";
        public const string SearchFld2 = "SearchFld2";
        public string AppName = "";
        private MgSiteConnection conn;
        private MgFeatureService featureService;
        private MgResourceService resourceService;
        private MgMap map;
        private MgLayer layer;
        private string sessionId = string.Empty;
        private utilityfunctions utils = new utilityfunctions();

        private bool _whithError = false;

        public  int matchLimit = 0;
        public int numCols = 0;
        public string locale = string.Empty;
        public string layerId = string.Empty;
        public string mapName = string.Empty;
        public string filter = string.Empty;
        public string acProperty = string.Empty;
        public string acLayer = string.Empty;
        public string property = string.Empty;
        public string NullFiledVal = string.Empty;
        public Dictionary<string, string> displayProperties;

        private bool distinct = false;
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            txtCities.Multiple = false;
            txtStreets.Multiple = false;
        }

        public void setfieldSession_viewState(string fieldName)
        {
            string fieldVal = string.Empty;
            fieldVal = Request[fieldName];

            ViewState.Add(fieldName, fieldVal);
            Session[fieldName] = fieldVal;
        
        }
        public string GetfieldSession_viewState(string fieldName)
        {
            string fieldVal = string.Empty;
            if (null != Session[fieldName])
            {
                fieldVal = Session[fieldName].ToString();
                
                }
            

            if (null != ViewState[fieldName])
            {
                fieldVal = ViewState[fieldName].ToString();
                
                
            }
        return fieldVal;
           
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            AppName = ConfigurationManager.AppSettings["appname"];
            if (!IsPostBack)
            {
                //Common variables
                sessionId = Request[KeySession];
                Session[KeySession] = sessionId;
                ViewState.Add(KeySession, sessionId);

                mapName = Request[KeyMapName];
                Session[KeyMapName] = mapName;
                ViewState.Add(KeyMapName, mapName);

                //Variables for autocomplete

                ViewState.Add("UserMassage", Request["UserMassage"]);
              //  btnSearch.Text = ViewState["UserMassage"].ToString();
                setfieldSession_viewState(SearchFld1);
                setfieldSession_viewState(SearchFld2);
                setfieldSession_viewState(IdField1);
                setfieldSession_viewState(IdField2);
                setfieldSession_viewState(KeyLayer1);
                setfieldSession_viewState(KeyLayer2);
              
                Session[KeyACLayer] = acLayer;

                NullFiledVal = Request[IdField1];

                ViewState.Add(IdField1, NullFiledVal);
                Session[IdField1] = NullFiledVal;

                acProperty = Request[KeyACProperty] ?? Request[KeyProperty];
                Session[KeyACProperty] = acProperty;

                bool isString = checkProperty(acProperty);
                Session[KeyIsString] = isString;

                //Variables for search
               
               
                
                int ix = 0;
                AdddrpMulti(GetAllCompletionList(" FeatId > 0 ", GetfieldSession_viewState(KeyLayer1), GetfieldSession_viewState(SearchFld1), GetfieldSession_viewState(KeySession), GetfieldSession_viewState(KeyMapName)), ref txtCities, "");

                //AdddrpMulti(GetAllCompletionList(" FeatId > 0 ", GetfieldSession_viewState(KeyLayer1), GetfieldSession_viewState(SearchFld1), GetfieldSession_viewState(KeySession), GetfieldSession_viewState(KeyMapName)), ref us, "");
                // NOT STREET NULL AND CITYNAME like 'באר שבע'
            }
            else
            {
                sessionId = ViewState[KeySession].ToString();
                mapName = ViewState[KeyMapName].ToString();
               // btnSearch.Text = ViewState["UserMassage"].ToString(); 
                //filter = ViewState[KeyFilter].ToString();
               // matchLimit = (int)ViewState[KeyMatchLimit];
                NullFiledVal = ViewState[IdField1].ToString();
            }

          //  string[] allcountries = 
               

            if (!_whithError)
            {
                _ErrorMessage.Visible = false;
            }
            _whithError = false;
        }

    
        private void GetPropertiesFields(Dictionary<string, string> columnCollection)
        {
            MgByteReader reader = resourceService.GetResourceContent(layer.LayerDefinition);
            string xmlSchema = reader.ToString();
            reader.Dispose();
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(xmlSchema);
            XmlNodeList xmlProperties = xmlDoc.GetElementsByTagName("PropertyMapping");
            foreach (XmlNode node in xmlProperties)
            {
                string Name = node.SelectSingleNode("Name").InnerText;
                string Alias = node.SelectSingleNode("Value").InnerText;
                columnCollection.Add(Name, Alias);
            }
        }
        private string[] GetPrimaryKeyFieldName()
        {
            string schemaName = layer.FeatureClassName.Split(':')[0];
            MgFeatureSchemaCollection schema = featureService.DescribeSchema(new MgResourceIdentifier(layer.FeatureSourceId), schemaName);

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(featureService.SchemaToXml(schema));

            XmlNamespaceManager nsmr = new XmlNamespaceManager(doc.NameTable);
            nsmr.AddNamespace("xs", "http://www.w3.org/2001/XMLSchema");

            XmlNodeList elements = doc.GetElementsByTagName("xs:key");
           // XmlNodeList nodes = elements[0].SelectNodes("xs:field", nsmr);
             XmlNodeList nodes = elements[0].SelectNodes("xs:field", nsmr);
           
            List<string> keys = new List<string>();
            foreach (XmlNode node in nodes)
            {
                keys.Add(node.Attributes["xpath"].Value);
            }
            return keys.ToArray();
        }
        private string GetValuesTable(MgFeatureReader reader, Dictionary<string, string> columnsCollection)
        {
            string[] keyFields = GetPrimaryKeyFieldName();
            List<string> ids = new List<string>();
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("<tbody>");
            bool alternate = true;
            int row = 0;
            bool hasResults = false;
            List<string> results = new List<string>();

            while (reader.ReadNext())
            {
                hasResults = true;
                bool isEmptyRow = true;
                StringBuilder sb1 = new StringBuilder();
                sb1.AppendLine(string.Format("<tr class='resultRow{0}'>", alternate ? "0" : "1"));
                alternate = !alternate;
                int column = 0;
                foreach (var item in columnsCollection)
                {
                    string val = string.Empty;
                    try
                    {
                        val = GetPropertyValue(reader, item.Key);

                        if (((bool)ViewState[KeyDistinct]) && results.Contains(val)) continue;
                        results.Add(val);
                        if (!string.IsNullOrEmpty(val))
                        {
                            sb1.AppendFormat("<td id='{1}:{2}' onclick=\"CellClicked('{3}')\">{0}</td>", val, row, column++, GetSelectionXml(reader, keyFields));
                            isEmptyRow = false;
                        }
                    }
                    catch { throw; }
                }
                sb1.AppendLine("</tr>");
                if (!isEmptyRow) sb.Append(sb1.ToString());
                if (++row == matchLimit) break;
            }
            sb.AppendLine("</tbody>");
            if (!hasResults) throw new doSearchException("אין תוצאות");
            return sb.ToString();
        }
        private string GetSelectionXml(MgFeatureReader reader, string[] keys)
        {
            MgSelection sel = new MgSelection(map);
            MgPropertyCollection idProps = new MgPropertyCollection();

            for (int i = 0; i < keys.Length; i++)
            {
                int idPropType = reader.GetPropertyType(keys[i]);
                switch (idPropType)
                {
                    case MgPropertyType.Int32:
                        idProps.Add(new MgInt32Property(keys[i], reader.GetInt32(keys[i])));
                        break;
                    case MgPropertyType.String:
                        idProps.Add(new MgStringProperty(keys[i], reader.GetString(keys[i])));
                        break;
                    case MgPropertyType.Int64:
                        idProps.Add(new MgInt64Property(keys[i], reader.GetInt64(keys[i])));
                        break;
                    case MgPropertyType.Double:
                        idProps.Add(new MgDoubleProperty(keys[i], reader.GetDouble(keys[i])));
                        break;
                    case MgPropertyType.Single:
                        idProps.Add(new MgSingleProperty(keys[i], reader.GetSingle(keys[i])));
                        break;
                    case MgPropertyType.DateTime:
                        idProps.Add(new MgDateTimeProperty(keys[i], reader.GetDateTime(keys[i])));
                        break;
                    default:
                        break;
                }
            }
            sel.AddFeatureIds(layer, layer.FeatureClassName, idProps);

            return HttpUtility.HtmlEncode(sel.ToXml());
        }
        private void ShowError(string message)
        {
            _whithError = true;
            _ErrorMessage.Visible = true;
            _ErrorMessage.Controls.Clear();
            _ErrorMessage.Controls.Add(new Label() { Text = message, CssClass = "doErrorMessage" });
            ResultPanel.Visible = false;
        }

        private void AdddrpMulti(string[] Values,ref  HtmlSelect listControl, string drpid)
        {
            foreach (string item in Values )
            {
               
                ListItem tete = new ListItem();
                tete.Text = item;
                tete.Value = item;
                listControl.Items.Add(tete);
            }
        }

        private StringCollection GetSelectedValuesOfSelect(HtmlSelect ControlToSearch)
        {
            StringCollection FilterSelected = new StringCollection();
            foreach (ListItem item in ControlToSearch.Items)
            {


                if (item.Selected)
                {
                    FilterSelected.Add(" " + GetfieldSession_viewState(SearchFld1) + " LIKE '" + item.Text + "' ");
                   
                }

            }

            return FilterSelected;
        
        }
        private string  SearchFilterBuilder(StringCollection valuestoFilter , string Operator)
        {
            string resultFilter = string.Empty;
            int countselected = 0;
            foreach (string item in valuestoFilter)
            {
                countselected++;

                if (countselected == valuestoFilter.Count)
                {
                    resultFilter += item;
                }
                else
                {
                    resultFilter += item + " " + Operator + " ";
                }

            }
            return resultFilter;
        
        }
        private MgLayer GetLayerToSearch(string _sessionid, string _mapName,string _layer )
        {       MgLayer return_layer;
            try
            {
                utils.InitializeWebTier();
                conn = new MgSiteConnection();
                conn.Open(new MgUserInformation(_sessionid));
                resourceService = conn.CreateService(MgServiceType.ResourceService) as MgResourceService;
                featureService = conn.CreateService(MgServiceType.FeatureService) as MgFeatureService;
                map = new MgMap();
                map.Open(resourceService, _mapName);
                return_layer = map.GetLayers().GetItem(_layer) as MgLayer;
                if (return_layer == null)
                {
                    throw new doSearchException("שכבה לא קיימת.");
                }

                StringCollection FilterSelected = new StringCollection();
                return return_layer;
            }
            catch(Exception erroExcp)
            {

                throw;
            }
        
        }
        private void DoMultiSearch(ref HtmlSelect controlToSearch)
        {
           string Filter = SearchFilterBuilder(GetSelectedValuesOfSelect(controlToSearch),"OR");
            map = GetMapByName(GetfieldSession_viewState(KeyMapName),GetfieldSession_viewState(KeySession));
            layer = GetLayerToSearch(GetfieldSession_viewState(KeySession),GetfieldSession_viewState(KeyMapName), GetfieldSession_viewState(KeyLayer1));

            string mainSelection = GetMainFeatureSelection(GetfieldSession_viewState(KeyLayer1), Filter,featureService);
            SetSelectedMultiValuesOnMap(GetXmlMultiselectFromFeature(Filter, map, layer, ref featureService), filter, layer, ref featureService);

           
        }
        private string GetXmlMultiselectFromFeature(string Filter , MgMap _map ,MgLayer _layer ,ref MgFeatureService _featureServ )
        {
            MgResourceIdentifier featureResId = new MgResourceIdentifier(_layer.GetFeatureSourceId());
            String className = _layer.GetFeatureClassName();
            String layerId2 = _layer.GetObjectId();
            MgFeatureQueryOptions layerQuery = new MgFeatureQueryOptions();
            layerQuery.SetFilter(Filter);
            MgFeatureReader featureReader = _featureServ.SelectFeatures(featureResId, className, layerQuery);

            MgSelection selection = new MgSelection(_map);

            selection.AddFeatures(_layer, featureReader, 0);

           return selection.ToXml();
        }
        private void SetSelectedMultiValuesOnMap(string XmlSelected, string filterq, MgLayer _layer, ref MgFeatureService _featureServ)
        {
            MgFeatureQueryOptions opt = new MgFeatureQueryOptions();
            opt.SetFilter(filterq);

            MgFeatureReader reader = _featureServ.SelectFeatures(
                                               new MgResourceIdentifier(_layer.FeatureSourceId),
                                               _layer.FeatureClassName,
                                               opt
                                            );

            

           
            string funcCall2 = string.Format("<script language='javascript'>CellClicked('{0}')</script>", XmlSelected);

            ClientScript.RegisterStartupScript(this.GetType(), "JSScript2", funcCall2);
                
        
        }
        public void SearchMulti(object sender, EventArgs e)
        {

            
           
            numCols = 1;

            Dictionary<string, string> displayColumns = new Dictionary<string, string>();
        try
            {

                DoMultiSearch(ref txtCities);




               
              string   acFilter = string.Empty;





              StringBuilder resultHtml = new StringBuilder();

                 
              

               
                ResultPanel.Visible = true;
                ResultContainer.Text = resultHtml.ToString();
            }
            catch (doSearchException ex)
            {
                _whithError = true;
                ShowError(ex.Message);
            }
            catch (MgException ex)
            {
                _whithError = true;
                if (__debugMode)
                    ShowError(ex.Message);
                else
                    ShowError("שגיאה, אנא וודא תקינות שאילתא.");
            }
               
              
                   
              
           

        }
     
        public string[] GetAllCompletionList(string filtertoseach, string LayertoSearch, string Propertytosearch, string sessionIdstr ,string MapName)
        {
          
           
               
           
            List<string> results = new List<string>();
            try
            {
                MgSiteConnection conn = new MgSiteConnection();
                conn.Open(new MgUserInformation(sessionIdstr));
                
                MgResourceService resourceService = conn.CreateService(MgServiceType.ResourceService) as MgResourceService;
                MgFeatureService featureService = conn.CreateService(MgServiceType.FeatureService) as MgFeatureService;
           
                MgMap map = new MgMap();
                map.Open(resourceService, MapName);
                MgLayer layer = (MgLayer)map.GetLayers().GetItem(LayertoSearch);
                MgFeatureQueryOptions query = new MgFeatureQueryOptions();
                //SelectAggregate MgFeatureQueryOptions SetFilter
                query.SetFilter(filtertoseach);
               

                MgFeatureReader reader = featureService.SelectFeatures(new MgResourceIdentifier(layer.GetFeatureSourceId()), layer.GetFeatureClassName(), query);
                while (reader.ReadNext())
                {
                   // string val = GetPropertyValue(reader, property);
                    string val = reader.GetString(Propertytosearch);
                    results.Add(val);
                    //if (val.StartsWith(prefixText) && !results.Contains(val)) results.Add(val);
                    //if (results.Count >= count) break;
                }
                reader.Close();
                reader.Dispose();
            }
            catch (Exception e)
            {
                results.Add(e.Message);
            }
            results.OrderBy(k => k);
            return results.ToArray();
        }
        [System.Web.Services.WebMethodAttribute(), System.Web.Script.Services.ScriptMethodAttribute()]
    
        private static string GetPropertyValue(MgFeatureReader reader, string propertyName)
        {
            string val = string.Empty;

            if (reader.IsNull(propertyName)) return val;

            switch (reader.GetPropertyType(propertyName))
            {
                case MgPropertyType.Boolean:
                    val = reader.GetBoolean(propertyName).ToString();
                    break;
                case MgPropertyType.Byte:
                    val = reader.GetByte(propertyName).ToString();
                    break;
                case MgPropertyType.Single:
                    val = reader.GetSingle(propertyName).ToString();
                    break;
                case MgPropertyType.Double:
                    val = reader.GetDouble(propertyName).ToString();
                    break;
                case MgPropertyType.Int16:
                    val = reader.GetInt16(propertyName).ToString();
                    break;
                case MgPropertyType.Int32:
                    val = reader.GetInt32(propertyName).ToString();
                    break;
                case MgPropertyType.Int64:
                    val = reader.GetInt64(propertyName).ToString();
                    break;
                case MgPropertyType.String:
                    val = reader.GetString(propertyName);
                    break;
                case MgPropertyType.DateTime:
                    val = reader.GetDateTime(propertyName).ToString();
                    break;
                case MgPropertyType.Null:
                case MgPropertyType.Blob:
                case MgPropertyType.Clob:
                case MgPropertyType.Feature:
                case MgPropertyType.Geometry:
                case MgPropertyType.Raster:
                    break;
            }
            return val;
        }
        private static bool checkProperty(string property, string layerName)
        {
            try
            {
                MgSiteConnection conn = new MgSiteConnection();
                conn.Open(new MgUserInformation(HttpContext.Current.Session[KeySession].ToString()));

                MgResourceService resourceService = conn.CreateService(MgServiceType.ResourceService) as MgResourceService;
                MgFeatureService featureService = conn.CreateService(MgServiceType.FeatureService) as MgFeatureService;

                MgMap map = new MgMap();
                map.Open(resourceService, HttpContext.Current.Session[KeyMapName].ToString());
                MgLayer layer = (MgLayer)map.GetLayers().GetItem(layerName);
                MgFeatureQueryOptions query = new MgFeatureQueryOptions();
                query.AddFeatureProperty("NAME");
                query.SetFilter(String.Format("FeatId=1", property,"NAME"));
                MgFeatureReader reader = featureService.SelectFeatures(new MgResourceIdentifier(layer.GetFeatureSourceId()), layer.GetFeatureClassName(), query);
                reader.ReadNext();
                int propertyType = reader.GetPropertyType(property);
                return propertyType == MgPropertyType.String;
            }
            catch (Exception e) { }
            return false;
        }
        private static bool checkProperty(string property)
        {
            return checkProperty(property, HttpContext.Current.Session[KeyACLayer].ToString());
        }

        private string GetMainFeatureSelection(string layerName, string filter, MgFeatureService _featureService)
        {
            string result = String.Empty;

            if (String.IsNullOrEmpty(layerName) || String.IsNullOrEmpty(filter))
                return result;

            MgLayer mLayer = map.GetLayers().GetItem(layerName) as MgLayer;
            MgFeatureQueryOptions opt = new MgFeatureQueryOptions();
            opt.SetFilter(filter);

            MgFeatureReader reader = _featureService.SelectFeatures(new MgResourceIdentifier(mLayer.FeatureSourceId), mLayer.FeatureClassName, opt);
            MgSelection sel = new MgSelection();
            sel.AddFeatures(mLayer, reader, 20);
            result = sel.ToXml();
            reader.Close();
            reader.Dispose();

            return result;
        }
    }
   
}